#include <futex.h>

typedef struct Lock      Lock;
typedef volatile uintptr Note;

struct Lock
{
	volatile uint32 init;   // init mark, because zeroed lock is considered unlocked
	futex_t futex;   // private access futex
};

/*
 * mutual exclusion locks.  in the uncontended case,
 * as fast as spin locks (just a few user-level instructions),
 * but on the contention path they sleep in the kernel.
 * a zeroed Lock is unlocked (no need to initialize each lock).
 */
void runtime_lock(Lock * l);
void runtime_unlock(Lock * l);

/*
 * sleep and wakeup on one-time events.
 * before any calls to notesleep or notewakeup,
 * must call noteclear to initialize the Note.
 * then, exactly one thread can call notesleep
 * and exactly one thread can call notewakeup (once).
 * once notewakeup has been called, the notesleep
 * will return.  future notesleep will return immediately.
 * subsequent noteclear must be called only after
 * previous notesleep has returned, e.g. it's disallowed
 * to call noteclear straight after notewakeup.
 */
void runtime_noteclear(Note * n);
void runtime_notewakeup(Note * n);
void runtime_notesleep(Note * n);
